#include "TouchKey.h"



//#0 ****************************   宏定义   *****************************************************************
/* TODO 根据实际情况修改以下宏定义 */
#define MCU_TOUCH_64BIT         1                       /* 芯片最大触摸通道(0:32 / 1:64) */
#define MCU_TOUCH_LOW_WORD      keys_flag_l             /* 触摸低字节 */
#define MCU_TOUCH_HIGH_WORD     keys_flag_h             /* 触摸高字节 */
#define POWER_KEY_REAL_STATUS   (readCache[5] & 0x04)   /* 开机键的真实位(物理)(用于检测有水可以关机) */



//#0 ****************************   变量定义   ***************************************************************
/* TODO 根据实际情况修改映射表 */
/* 按键映射表 */
static SYS_CONST uint8_t u8TouchKeyMap[]=
{
    //? 芯片 0-31 通道
    0,  // channel_0
    0,  // channel_1
    0,  // channel_2
    0,  // channel_3
    0,  // channel_4
    0,  // channel_5
    KEY_VAL_FURNACE_B,  // channel_6
    KEY_VAL_FURNACE_A,  // channel_7

    0,  // channel_8
    0,  // channel_9
    KEY_VAL_LOCK,       // channel_10
    KEY_VAL_SLIDE_A3,   // channel_11
    0,  // channel_12
    0,  // channel_13
    0,  // channel_14
    0,  // channel_15

    KEY_VAL_SLIDE_A1,   // channel_16
    KEY_VAL_SLIDE_A0,   // channel_17
    KEY_VAL_SLIDE_A9,   // channel_18
    KEY_VAL_SLIDE_A7,   // channel_19
    0,  // channel_20
    0,  // channel_21
    0,  // channel_22
    0,  // channel_23

    0,  // channel_24
    0,  // channel_25
    0,  // channel_26
    0,  // channel_27
    KEY_VAL_SLIDE_A5,   // channel_28
    KEY_VAL_BOOST,      // channel_29
    KEY_VAL_TIMER,      // channel_30
    0,  // channel_31

#if MCU_TOUCH_64BIT
    //? 芯片 32-63 通道
    0,  //channel_32
    0,  //channel_33
    0,  //channel_34
    0,  //channel_35
    0,  //channel_36
    0,  //channel_37
    0,  //channel_38
    KEY_VAL_FURNACE_D,  //channel_39
    KEY_VAL_FURNACE_C,  //channel_40

    0,  //channel_41
    0,  //channel_42
    KEY_VAL_POWER_ON_OFF,   //channel_43
    0,  //channel_44
    0,  //channel_45
    0,  //channel_46
    0,  //channel_47

    0,  //channel_48
    0,  //channel_49
    0,  //channel_50
    0,  //channel_51
    0,  //channel_52
    0,  //channel_53
    0,  //channel_54
    0,  //channel_55

    0,  //channel_56
    0,  //channel_57
    0,  //channel_58
    0,  //channel_59
    0,  //channel_60
    0,  //channel_61
    0,  //channel_62
    0,  //channel_63
#endif
};

/* 组合键映射表 */
static SYS_CONST uint8_t u8CombinedKeyMap[][3]=
{
    /* 按键1                    按键2                       组合键值 */
    {KEY_VAL_SLIDE_A0,          KEY_VAL_SLIDE_A1,          KEY_VAL_SLIDE_A1},
    {KEY_VAL_SLIDE_A1,          KEY_VAL_SLIDE_A3,          KEY_VAL_SLIDE_A2},
    {KEY_VAL_SLIDE_A3,          KEY_VAL_SLIDE_A5,          KEY_VAL_SLIDE_A4},
    {KEY_VAL_SLIDE_A5,          KEY_VAL_SLIDE_A7,          KEY_VAL_SLIDE_A6},
    {KEY_VAL_SLIDE_A7,          KEY_VAL_SLIDE_A9,          KEY_VAL_SLIDE_A8},
};



//#1 ****************************   功能实现   ***************************************************************
/************************************************************************************************************
 * @功能:    从总线中读取按键
 * @参数:    pData: 数据缓存
 * @返回:    GET_TOUCH_KEY_SUCCESS 或者 GET_TOUCH_KEY_FAIL
************************************************************************************************************/
static uint8_t read_touch_key_from_bus(uint8_t SYS_RAM *pData)
{
    /* TODO 通过总线读取按键的时候, 需要在这里实现总线读取 */
    pData[0] = MCU_TOUCH_LOW_WORD &  0xff;
    pData[1] = MCU_TOUCH_LOW_WORD >> 8;
    pData[2] = MCU_TOUCH_LOW_WORD >> 16;
    pData[3] = MCU_TOUCH_LOW_WORD >> 24;
#if MCU_TOUCH_64BIT
    pData[4] = MCU_TOUCH_HIGH_WORD &  0xff;
    pData[5] = MCU_TOUCH_HIGH_WORD >> 8;
    pData[6] = MCU_TOUCH_HIGH_WORD >> 16;
    pData[7] = MCU_TOUCH_HIGH_WORD >> 24;
#endif
    return GET_TOUCH_KEY_SUCCESS;
}

/************************************************************************************************************
 * @功能:    获取按键1和按键2
 * @参数:    pData: 按键数据
 * @参数:    key1:  按键1
 * @参数:    key2:  按键2
 * @返回:    按键按下数量
************************************************************************************************************/
static uint8_t get_touch_key1_and_key2(const uint8_t SYS_RAM *pData, uint8_t SYS_RAM *key1, uint8_t SYS_RAM *key2)
{
    uint8_t  value = 0;         /* 按键1 */
    uint8_t  shift = 0;         /* 按键2 */
    uint8_t  count = 0;         /* 按下数量 */
    uint8_t  i;
    uint8_t  dat;
    uint8_t  index;

#if MCU_TOUCH_64BIT
    for (i = 0; i < 8; i++)
#else
    for (i = 0; i < 4; i++)
#endif
    {
        dat = pData[i];
        index = 0;

        while (dat != 0)
        {
            if (dat & 0x01)
            {
                count++;
                if (count      == 1)
                {
                    value = index + (i << 3);
                }
                else if (count == 2)
                {
                    shift = index + (i << 3);
                }
                else
                {
                    goto fun_exit;
                }
            }

            index++;
            dat >>= 1;
        }
    }

    /* 退出函数 */
    fun_exit:
    *key1 = value;
    *key2 = shift;
    return count;
}

/************************************************************************************************************
 * @功能:    获取按键键值
 * @参数:    pkeyValue: 按键键值
 * @参数:    pkeyPower: 电源键状态
 * @返回:    GET_TOUCH_KEY_SUCCESS 或者 GET_TOUCH_KEY_FAIL
************************************************************************************************************/
uint8_t get_touch_key(uint8_t *pkeyValue, uint8_t *pkeyPower)
{
    #if MCU_TOUCH_64BIT
        static SYS_RAM uint8_t readCache[8];
    #else
        static SYS_RAM uint8_t readCache[4];
    #endif

    /* 从总线中读取按键, 获取成功后进行键值输出 */
    if (read_touch_key_from_bus(readCache) == GET_TOUCH_KEY_SUCCESS)
    {
        static SYS_RAM uint8_t value = 0;           /* 第一个键 */
        static SYS_RAM uint8_t shift = 0;           /* 第二个键 */
        static SYS_RAM uint8_t pressNumber = 0;     /* 本次按键个数 */
        static SYS_RAM uint8_t lastNumber = 0;      /* 上次按键个数 */
        static SYS_RAM uint8_t lastEffective = 0;   /* 上次有效键值 */
        static SYS_RAM uint8_t insidekeyValue = 0;  /* 内部键值, 函数返回时, 赋值给形参 */

        /* 开关键的真实位(物理)(用于检测有水可以关机) */
        if (POWER_KEY_REAL_STATUS)
        {
            *pkeyPower = KEY_VAL_POWER_ON_OFF;
        }
        else
        {
            *pkeyPower = KEY_VAL_NONE;
        }

        /* 获取 第一个键 和 第二个键 和 本次按键按下个数 */
        pressNumber = get_touch_key1_and_key2(readCache, &value, &shift);

        /* 多键按下, 所有按键松开才能进行有效的键值输出(滑条不处理) */
        if (lastEffective >= KEY_VAL_POWER_ON_OFF)
        {
            if (insidekeyValue != KEY_VAL_INVALID)
            {
                if ((lastNumber >= 2) && (pressNumber != 0))
                {
                    /* 上次按下数量和这次不同, 输出无效等待释放键值 */
                    if (lastNumber != pressNumber)
                    {
                        insidekeyValue = KEY_VAL_INVALID_WAIT_UP;
                    }

                    /* 返回成功 */
                    *pkeyValue = insidekeyValue;
                    return GET_TOUCH_KEY_SUCCESS;
                }
            }
            else
            {
                if (pressNumber != 0)
                {
                    *pkeyValue = insidekeyValue;
                    return GET_TOUCH_KEY_SUCCESS;
                }
            }
        }

        /* 根据按键按下数量进行键值判断 */
        switch (pressNumber)
        {
            /* 无 */
            case 0:
            {
                insidekeyValue = 0;
                lastEffective  = 0;
                lastNumber     = 0;
            }break;

            /* 单键 */
            case 1:
            {
                insidekeyValue = u8TouchKeyMap[value];
                lastEffective  = insidekeyValue;
                lastNumber     = pressNumber;
            }break;

            /* 双键组合 */
            case 2:
            {
                uint8_t i             = 0;
                uint8_t combinedIndex = 0;
                uint8_t combinedLen   = sizeof(u8CombinedKeyMap) / sizeof(u8CombinedKeyMap[0]);
                value          = u8TouchKeyMap[value];
                shift          = u8TouchKeyMap[shift];
                lastNumber     = pressNumber;
                insidekeyValue = KEY_VAL_INVALID;

                /* 查找组合键 */
                for (i = 0; i < 2; i++)
                {
                    /* 循环第二次, 交换键值 */
                    if (i == 1)
                    {
                        uint8_t tmp = shift;
                        shift = value;
                        value = tmp;
                    }

                    /* 组合键判断 */
                    for (combinedIndex = 0; combinedIndex < combinedLen; combinedIndex++)
                    {
                        if ((value == u8CombinedKeyMap[combinedIndex][0]) && (shift == u8CombinedKeyMap[combinedIndex][1]))
                        {
                            insidekeyValue = u8CombinedKeyMap[combinedIndex][2];
                            break;
                        }
                    }

                    /* 有效键值备份 */
                    if (insidekeyValue != KEY_VAL_INVALID)
                    {
                        lastEffective = insidekeyValue;
                        break;
                    }
                }
            }break;

            /* 双键以上 */
            default:
            {
                insidekeyValue = KEY_VAL_INVALID;
                lastEffective  = KEY_VAL_INVALID;
                lastNumber     = pressNumber;
            }break;
        }

        /* 返回成功 */
        *pkeyValue = insidekeyValue;
        return GET_TOUCH_KEY_SUCCESS;
    }
    else
    {
        return GET_TOUCH_KEY_FAIL;
    }
}
